# python里的一些骚操作

# 同时多个赋值用,分隔开即可
a, b, c = 1, 2, 3
# print(a, b, c)

# python里特殊的数据类型 复数complex  复数的实部和虚部都是浮点型
d1 = 4+3j    # <class 'complex'>
d2 = complex(4, 5)  # (4+5j)

# True 和 False 虽然是bool类型 但值是1和0 它们仍然可以和数字运算
e = 3 - True    # (int)2

# 除法运算分为两种
a1 = 10/4   # (float)2.5
a2 = 10//4  # (int)2

# 数据类型的转化 int()把符合规则的字符串类型转化为整数
# 下面这行会报错 因为小数形式的字符串是不能用
# b1 = int('2.5')
# 浮点型是可以通过 int() 转换的 且转换方式为取整
b2 = int(float('2.99'))  # (int)2

# 常量折叠操作
aaa, bbb = "crazy!", "crazy!"
# print(aaa is bbb)     #3.6 返回True  3.7返回 False 

# print('a' * 20 is 'aaaaaaaaaaaaaaaaaaaa')     # True
# print('a' * 21 is 'aaaaaaaaaaaaaaaaaaaaa')    # False


# 关键字 assert 断言 如果条件为假的话会使程序崩溃抛出 AssertionError 的异常
# 后为真 什么都不会发生
assert 1 < 100
# 解封下面这行run一下试试?
# assert 10 - 10

# BIF 即(built-in functions)内置函数
# 用魔术方法查看python所有的内置函数
# print(dir(__builtins__))

# help()可以看到内置函数的用法说明 自带文档真的666
# help(pow)

# 强大的列表 list
# 列表型可以用使用运算符  从列表的第0个元素进行比较，若相等，则继续下一个比较 得到的结果是布尔值
list1 = [111, 111]
list2 = [111, 222]
# print(list1 < list2)   # True
# print(list1 == list2    # False
# print(list2 + list1)  # [111, 222, 111, 111]
# print(list1 and list2)    #[111, 222]
# print(list2*3)  # [111, 222, 111, 222, 111, 222]
# 声明列表用[]
member = ['路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇']
# 方括号的形式截取字符[:] 为左臂右开区间 起始默认0 结尾默认最后一个元素 如果啥都不写等于复制了一份列表
copy_member = member[:]
copy_member2 = member
copy_member3 = member.copy()
# 给列表里插入新元素
member.insert(0, "未知成员")
# print(member)   # ['未知成员', '路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇']
# print(copy_member)   # ['路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇']
# 如果不用列表.copy() 直接用等号赋值的话 传递的是储存地址 原列表变化则copy_member2也会变化
# print(copy_member2)    # ['未知成员', '路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇']
# print(copy_member3)     # ['路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇']
# 其他常用方法 remove() 删除列表内的元素 有复数个相同值的时候只删除从0起的第一个值
# 如果不存在这个值会报错
if "未知成员" in member:
    member.remove("未知成员")

# append() 往列表的最后位增加元素
# member.append("aaa")  #['路飞', '索隆', '山治', '娜米', '乌索普', '罗宾', '乔巴', '布鲁克', '弗兰奇', 'aaa']
# pop()函数很适合遍历用一次就扔的list 不加参数时默认pop出最后一个元素
# len()数元素数量 count("一个值")数"一个值"的出现次数
# 把字符串打散成列表 split()
date = "2020-01-18"
date.split("-")     # ['2020', '01', '18']
# 把字符串访入列表元素后 拼接成新的字符串
my_string = "asdf"
my_string.join(member)  # 路飞asdf索隆asdf山治asdf娜米asdf乌索普asdf罗宾asdf乔巴asdf布鲁克asdf弗兰奇


# 列表的好基友--元组 tuple
# tuple一旦初始化就不能修改,也就是说不可变的，没有 append()，insert(),可以取值但是不能赋值
# 元组中通常存储不同数据类型
# 觉得不爽的话 用list(seq) 可以把元组转为列表 也可以tuple(seq)列表转化元组 互换方便
# 元组用小括号定义 如果只有一个元素后边要加个逗号 否则...
tuple_start = ("123")
type(tuple_start)   # <class 'str'> 人工智障无法判断出你要创建元组还是只是要一个字符串

tuple_start = ("555",)
type(tuple_start)   # <class 'tuple'> 元组创建成功
# 同时上面这个操作还说明,虽然元组里面的值不能修改 但可以整个盖掉重写
# 元组里的元素也不能删除 除非你删整个元组
# 元组依然可以使用运算符进行拼接
tuple_member = ('路飞', 'NAROTO', '黒崎一護', 666, ['aaa', 'bbb'])
tuple_member1 = ('小当家', '海绵宝宝')
# print(tuple_member + tuple_member1)  # ('路飞', 'NAROTO', '黒崎一護', 666, ['aaa', 'bbb'], '小当家', '海绵宝宝')
# print(tuple_member * 2)  # ('路飞', 'NAROTO', '黒崎一護', 666, ['aaa', 'bbb'], '路飞', 'NAROTO', '黒崎一護', 666, ['aaa', 'bbb'])
# 格式化字符串 本质上就是一个元组
info_tuple = ("小明", 18, 1.669)
print("%s 年龄是 %d 身高是 %.2f" % info_tuple)


# 键值对数组--字典 Dictionary
# 字典就相当于 JAVA 中的 map，使用键-值（key-value）存储，具有极快的查找速度。
# 每个键值(key=>value)对用冒号(:)分割
# 键必须是唯一的，但值则不必。
dict_test = {'你': 3333333, '我': '555', '他': True, 2: "海贼王"}
# 访问字典型 使用key
dict_test["我"]  # 555
# 如果不存在这个键 就会报错 比如 dict_test[123]
# dict的灵魂是key值 比如用常用的 in 检测的话 列表和元组都是检测值是否存在 而字典检测的是key值是否存在
# print('555' in dict_test)   # False
# print('我' in dict_test)     # True

# 遍历字典键值对
for k, v in dict_test.items():
    pass
# pop字典 最后一个键值对
get_one = dict_test.popitem()


# 键名重复时会以最后一次赋值为准
dict_test2 = {'你': 3333333, '我': '555', '他': True, 2: "海贼王", '他': complex(4, 5)}
# print(dict_test2)     #{'你': 3333333, '我': '555', '他': (4+5j), 2: '海贼王'}
# 键名不可变 键可以用数字，字符串或元组充当，但是就是不能使用列表

# dict 与 list 对比
# dict 内部存放的顺序和 key 放入的顺序是没有关系 因此查找和插入的速度极快，不会随着key的增加而变慢
# 缺点:需要占用大量的内存，内存浪费多
# list 查找和插入的时间随着元素的增加而增加
# 数字键 所以占用空间小

# set 是一个无序不重复元素集 和dict类似，但是set不存储 value 值的。
# 创建set，需要提供一个 list

lise_for_set = [111, 222, 123, "555", 555, 111]
new_set = set(lise_for_set)     # {555, 111, 123, 222, '555'}
# 显示的顺序跟list里的元素的顺序是不一致的，这也说明了set是无序的
# 复元素在 set 中自动被过滤的 但是555数据类型不同 保留下来了
# set 可以理解为只保存 key 值的字典

# 通过 add(key)增加元素  remove(key)删除
# set的妙用  set 是无序不重复元素集 所以可以做并集,交集, 差集等操作。
set1 = set('hello')     # {'e', 'o', 'l', 'h'}
set2 = set(['p', 'y', 'y', 'h', 'o', 'n'])   # {'o', 'h', 'y', 'n', 'p'}
set3 = set1 & set2  # 取交集 {'o', 'h'}
set4 = set1 | set2  # 取并集 {'l', 'n', 'h', 'e', 'o', 'y', 'p'}
set5 = set1 - set2      # set1 - set2 差集 {'l', 'e'}
set6 = set2 - set1      # set2 - set1 差集{'y', 'n', 'p'}

# 复合嵌套使用的时候需注意地址的引用
# 列表,字典 = 复制 对应同一个引用地址
# 深复制 copy.deepcopy() 两个是完全独立的，改变任意一个的元素（无论是多少层），另一个绝不会改变。
# 浅复制 copy() 第一层创建新的内存地址。而从第二层开始，指向的是同一个内存地址，对于第二层以及更深的层数来说，保持一致性。


# is 和 == 比较的不同
# is比较的是id是不是一样，==比较的是值是不是一样。
# Python中，万物皆对象,每个对象包含3个属性，id，type，value
# id就是对象地址,type类型，value值。


a = 1
b = a
c = 1
d = 1.0
# print(id(a))   # 1583198432
# print(id(b))   # 1583198432
# print(id(c))   # 1583198432
# print(id(d))   # 2693688992368

# 判断 a is c 的时候 其实等同于判断 id(a)==id(c)
# 用is的效率 高于==的效率
# 需要注意下面的情况
# print(a == d)      # True
# print(a is d)      # False




